package com.freewater.springboot.demo.aop.api.advices.after;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterAdvice;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import javax.annotation.Nonnull;
import java.io.Serial;
import java.io.Serializable;

public class MethodAfterFinalAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    private final AfterFinalAdvice advice;

    /**
     * Create a new MethodAfterFinalAdviceInterceptor for the given advice.
     *
     * @param advice the AfterFinalAdvice to wrap
     */
    public MethodAfterFinalAdviceInterceptor(AfterFinalAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }


    @Override
    @Nullable
    public Object invoke(@Nonnull MethodInvocation mi) throws Throwable {
        Object result = null;
        Throwable throwable = null;
        try {
            result = mi.proceed();
        } catch (Throwable e) {
            throwable = e;
        }
        this.advice.after(result, mi.getMethod(), mi.getArguments(), mi.getThis());
        if (throwable != null) {
            throw throwable;
        }
        return result;
    }
}